﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Myotragus.Data.Containers;
using Myotragus.Data.Domain;

namespace Myotragus.Data.Metadata
{
	public class LocalizableEntityDescriptor<TEntity> :
		EntityDescriptor<TEntity>,
		ILocalizableEntityDescriptor<TEntity>
		where TEntity : IEntity
	{
		#region Creation

		public LocalizableEntityDescriptor(IEntitiesContainer entities, ILocalizableEntityMapping mapping)
			: this(mapping, entities.ResolveType(TypeOfISaveEntity), entities.ResolveType(TypeOfILoadEntity))
		{
		}

		protected ILocalizableEntityMapping Mapping { get; private set; }

		protected LocalizableEntityDescriptor(ILocalizableEntityMapping mapping, 
			Type saveEntity, Type loadEntity)
		{
			Mapping = mapping;
			LstLocalizablePropertiesNames = CreateLocalizablePropertiesList();

			SaveEntityImplementation = saveEntity;
			LoadEntityImplementation = loadEntity;

			DicSaveEntityProperties = CreatePropertiesDic(saveEntity);
			DicLoadEntityProperties = CreatePropertiesDic(loadEntity);
		}

		#endregion Creation

		#region Fields && Constants

		protected static readonly Type TypeOfISaveEntity = typeof(ISaveEntity<TEntity>);
		protected static readonly Type TypeOfILoadEntity = typeof(ILoadEntity<TEntity>);

		protected readonly IEnumerable<string> LstLocalizablePropertiesNames;

		protected IDictionary<string, PropertyInfo> DicSaveEntityProperties;
		protected IDictionary<string, PropertyInfo> DicLoadEntityProperties;

		private IEnumerable<string> CreateLocalizablePropertiesList()
		{
			return Mapping.GetLocalizableProperties(TypeOfTEntity).Select(p => p.PropertyName);
		}

		#endregion Fields && Constants

		#region Implementation of ILocalizableEntityTypeDescriptor<TEntity,TSaveEntity,TLoadEntity>

		public IEnumerable<string> LocalizableProperties
		{
			get { return LstLocalizablePropertiesNames; }
		}

		public IDictionary<string, PropertyInfo> LoadEntityProperties
		{
			get { return DicLoadEntityProperties; }
		}

		public IDictionary<string, PropertyInfo> SaveEntityProperties
		{
			get { return DicSaveEntityProperties; }
		}

		public Type SaveEntityImplementation
		{
			get;
			private set;
		}

		public Type LoadEntityImplementation
		{
			get;
			private set;
		}

		#endregion Implementation of ILocalizableEntityTypeDescriptor<TEntity,TSaveEntity,TLoadEntity>
	}
}